package J11_9;

import java.util.*;
import java.io.*;

public class Test4 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());

        int[] W = new int[N];
        int[] H = new int[N];
        int[] B = new int[N];
        long sumB = 0;
        long totalWeight = 0;

        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            W[i] = Integer.parseInt(st.nextToken());
            H[i] = Integer.parseInt(st.nextToken());
            B[i] = Integer.parseInt(st.nextToken());
            sumB += B[i];
            totalWeight += W[i];
        }

        // 最大允许的头部重量
        long maxHeadWeight = totalWeight / 2;

        // 计算每个部件分配到头部的收益增量 (H[i] - B[i])
        int[] delta = new int[N];
        for (int i = 0; i < N; i++) {
            delta[i] = H[i] - B[i];
        }

        // 动态规划：使用一维数组优化空间
        // dp[w] 表示头部总重量为w时的最大收益增量
        long[] dp = new long[(int) (totalWeight + 1)];
        Arrays.fill(dp, Long.MIN_VALUE);
        dp[0] = 0;  // 初始状态：头部重量0，收益0

        for (int i = 0; i < N; i++) {
            int weight = W[i];
            int gain = delta[i];
            // 从大到小遍历，避免覆盖未处理的状态
            for (long w = totalWeight; w >= 0; w--) {
                if (dp[(int) w] != Long.MIN_VALUE) {
                    // 选择将当前部件分配到头部
                    long newW = w + weight;
                    if (newW <= totalWeight) {
                        dp[(int) newW] = Math.max(dp[(int) newW], dp[(int) w] + gain);
                    }
                }
            }
        }

        // 寻找符合条件的最大收益
        long maxDelta = Long.MIN_VALUE;
        for (long w = 0; w <= maxHeadWeight; w++) {
            if (w <= totalWeight && dp[(int) w] > maxDelta) {
                maxDelta = dp[(int) w];
            }
        }

        // 总快乐 = 基础快乐(sumB) + 最大增量
        System.out.println(sumB + maxDelta);
    }
}
